package com.example.flutterprintapp;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.widget.Toast;

import androidx.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.flutter.Log;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {

    private static final String TAG = "AndroidPrinterTag";
    private static final String GET_SCANDATA = "nlscan.action.SCANNER_RESULT";
    private static final String SCAN_DATA = "SCAN_BARCODE1";
    public static final int UPDATE_LIST = 0x1000;
    private static final String METHOD_CHANNEL = "com.mx.print/method_channel";
    private MethodChannel methodChannel;
    private static final String DEVICE_SCAN = "device_scan";
    private static final String GET_BLUE_DEVICES = "get_blue_devices";
    private static final String OPEN_PRINT = "open_print";
    private static final String SEND_STRING = "send_string";
    private static final String SEND_QR_STRING = "send_qr_string";
    private static final String SEND_BAR_STRING = "send_bar_string";
    private static final String SEND_BYTES = "send_bytes";
    private static final String CLOSE_PRINT = "close_print";
    private static final String PRINT_TEST = "print_test";
    private static final int BLUE_ENABLE_REQUEST_CODE = 1001;
    private BluetoothAdapter bluetoothAdapter;
    private MethodChannel.Result channelResult;

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        android.content.IntentFilter filter = new android.content.IntentFilter();
        filter.addAction(GET_SCANDATA);
        registerReceiver(mScanResultReceiver, filter);
        methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), METHOD_CHANNEL);
        methodChannel.setMethodCallHandler((call, result) -> {
            switch (call.method) {
                case GET_BLUE_DEVICES:
                    channelResult = result;
                    getBlueDevicesStatus();
                    break;
                case OPEN_PRINT:
                    String deviceAddress = call.arguments();
                    Map<String, Object> res = new HashMap<>();
                    if (!BtSPP.OpenPrinter(deviceAddress)) {
                        res.put("result", false);
                        res.put("msg", BtSPP.ErrorMessage);
                        result.success(res);
                        return;
                    }
                    res.put("result", true);
                    res.put("msg", "open printer success");
                    result.success(res);
                    break;
                case SEND_BYTES:
                    try {
                        byte[] printBytes = call.arguments();
                        boolean printByteFlag = BtSPP.SPPWrite(printBytes);
                        result.success(printByteFlag);
                    } catch (Exception ex) {
                        result.success(false);
                    }
                    break;
                case SEND_STRING:
                    try {
                        String printString = call.arguments();
                        boolean printStringFlag = BtSPP.SPPWrite(printString.getBytes("GBK"));
                        result.success(printStringFlag);
                    } catch (UnsupportedEncodingException ex) {
                        result.success(false);
                    }
                    break;
                case SEND_BAR_STRING:
                    printBar(call.arguments(), result);
                    break;
                case SEND_QR_STRING:
                    String printQRString = call.arguments();
                    printQR(printQRString, result);
                    break;
                case CLOSE_PRINT:
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    boolean closeFlag = BtSPP.SPPClose();
                    result.success(closeFlag);
                    break;
                case PRINT_TEST:
                    String address = call.arguments();
                    printTest(address);
                    break;
            }
        });
    }

    /**
     * 获取连接的蓝牙适配器状态
     */
    private void getBlueDevicesStatus() {
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, BLUE_ENABLE_REQUEST_CODE);
        } else {
            getGetBlueDevicesList();
        }
    }

    /**
     * 获取蓝牙设备列表
     */
    private void getGetBlueDevicesList() {
        List<Map<String, String>> devicesList = new ArrayList<>();
        Set<BluetoothDevice> blueDevices = bluetoothAdapter.getBondedDevices();
        if (blueDevices.size() <= 0) {
            channelResult.success(devicesList);
            return;
        }
        for (BluetoothDevice device : blueDevices) {
            Map<String, String> map = new HashMap<>();
            map.put("deviceName", device.getName());
            map.put("deviceAddress", device.getAddress());
            devicesList.add(map);
        }
        channelResult.success(devicesList);
    }

    /**
     * 打印条形码
     *
     * @param content
     * @param result
     */
    private void printBar(String content, MethodChannel.Result result) {
        byte[] contentBytes = content.getBytes();
        byte contentSizeByte = (byte) contentBytes.length;
        BtSPP.SPPWrite(new byte[]{0x1D, 0x6B, 0x45, contentSizeByte});
        boolean flag = BtSPP.SPPWrite(contentBytes);
        result.success(flag);
    }

    /**
     * 打印二维码
     *
     * @param content
     * @param result
     */
    private void printQR(String content, MethodChannel.Result result) {
        try {
            BtSPP.SPPWrite(new byte[]{0x1D, 0x77, 0x04});//条码宽度4倍
            BtSPP.SPPWrite(new byte[]{0x1D, 0x5A, 0x01});//选择DataMatrix条码
            short strDataMatrixLen = (short) content.getBytes("GBK").length;
            BtSPP.SPPWrite(content.getBytes("GBK"));
            boolean printQRFlag = BtSPP.SPPWrite(new byte[]{0x1B, 0x5A, 0x00, 0x00, 0x00, (byte) (strDataMatrixLen & 0x00FF), (byte) (strDataMatrixLen / 256)});
            BtSPP.SPPWrite(content.getBytes("GBK"));
            BtSPP.SPPWrite("\n".getBytes("GBK"));
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
            result.success(printQRFlag);
        } catch (UnsupportedEncodingException ex) {
            result.success(false);
        }
    }

    /**
     * 测试打印功能
     *
     * @param address
     */
    private void printTest(String address) {
        if (!BtSPP.OpenPrinter(address)) {
            Toast.makeText(this, BtSPP.ErrorMessage, Toast.LENGTH_LONG).show();
            return;
        }
        try {
            BtSPP.SPPWrite(new byte[]{0x1B, 0x40});        //打印机复位
            BtSPP.SPPWrite("\n".getBytes("GBK"));

            BtSPP.SPPWrite(new byte[]{0x1B, 0x61, 0x01});    //居中
            BtSPP.SPPWrite("*****华丽的分割线*****\n".getBytes("GBK"));

            BtSPP.SPPWrite(new byte[]{0x1B, 0x61, 0x00});    //居左
            BtSPP.SPPWrite("测试开始\n".getBytes("GBK"));

            BtSPP.SPPWrite("(1、标题，居中，3倍大小，下划线，粗体)\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1B, 0x61, 0x01});    //居中
            BtSPP.SPPWrite(new byte[]{0x1D, 0x21, 0x22});    // 3倍字体大小
            BtSPP.SPPWrite(new byte[]{0x1B, 0x45, 0x01});    // 粗体
            BtSPP.SPPWrite(new byte[]{0x1B, 0x2D, 0x32});    // 2点粗下划线
            BtSPP.SPPWrite("标题\n".getBytes("GBK"));

            BtSPP.SPPWrite(new byte[]{0x1B, 0x61, 0x00});    //左对齐
            BtSPP.SPPWrite(new byte[]{0x1B, 0x21, 0x00});    // 还原默认字体大小，取消下划线，取消粗体模式
            BtSPP.SPPWrite("(2、条码：左对齐）\n".getBytes("GBK"));
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
            BtSPP.SPPWrite(new byte[]{0x1D, 0x6B, 0x45, 0x0D, 0x31, 0x39, 0x41, 0x54, 0x5A, 0x2D, 0x2E, 0x20, 0x24, 0x2F, 0x2B, 0x25, 0x44});    //code 39 条码：19ATZ-. $/+%D
            BtSPP.SPPWrite("\n".getBytes("GBK"));

            BtSPP.SPPWrite("（3、正文1，默认打印模式，绝对打印位置5mm）\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1B, 0x24, 0x28, (byte) 0x80});    // 设置绝对打印位置5mm，80表示00
            BtSPP.SPPWrite("1、0123456789-ABCD-9876543210中文测试。2、0123456789-ABCD-9876543210中文测试。3、0123456789-ABCD-9876543210中文测试。\n".getBytes("GBK"));

            BtSPP.SPPWrite("（4、继续条码，居中）\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1B, 0x61, 0x01});    //居中
            BtSPP.SPPWrite(new byte[]{0x1D, 0x6B, 0x45, 0x0D, 0x31, 0x39, 0x41, 0x54, 0x5A, 0x2D, 0x2E, 0x20, 0x24, 0x2F, 0x2B, 0x25, 0x44});    //code 39 条码：19ATZ-. $/+%D
            BtSPP.SPPWrite("\n".getBytes("GBK"));

            BtSPP.SPPWrite(new byte[]{0x1B, 0x61, 0x00});    //左对齐
            BtSPP.SPPWrite("（5、左对齐 0x3F点行间距）\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1B, 0x33, 0x1E});    //设置行间距为：3.75mm
            BtSPP.SPPWrite("以下是校长高震东在国内的讲演：\n".getBytes("GBK"));

            BtSPP.SPPWrite(new byte[]{0x1B, 0x32});    //设置默认行间距：1mm
            BtSPP.SPPWrite("（6、默认行间距）\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1B, 0x24, 0x28, (byte) 0x80});    // 设置绝对打印位置5mm，80表示00
            BtSPP.SPPWrite("1、0123456789-ABCD-9876543210中文测试。2、0123456789-ABCD-9876543210中文测试。3、0123456789-ABCD-9876543210中文测试。\n".getBytes("GBK"));

            BtSPP.SPPWrite("（7 、条码）\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1D, 0x6B, 0x02, 0x30, 0x31, 0x37, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00});    //EAN8：01712345
            BtSPP.SPPWrite("\n".getBytes("GBK"));
            BtSPP.SPPWrite("(8、二维条码DataMatrix)\n".getBytes("GBK"));
            BtSPP.SPPWrite(new byte[]{0x1D, 0x77, 0x04});        //条码宽度4倍
            BtSPP.SPPWrite(new byte[]{0x1D, 0x5A, 0x01});        //选择DataMatrix条码
            String strDataMatrix = "123-DataMatrix-二维码测试-321\0";
            short strDataMatrixLen = (short) strDataMatrix.getBytes("GBK").length;
            //打印DataMatrix条码
            BtSPP.SPPWrite(new byte[]{0x1B, 0x5A, 0x00, 0x00, 0x00, (byte) (strDataMatrixLen & 0x00FF), (byte) (strDataMatrixLen / 256)});
            BtSPP.SPPWrite(strDataMatrix.getBytes("GBK"));
            BtSPP.SPPWrite("\n".getBytes("GBK"));
        } catch (UnsupportedEncodingException e) {
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        BtSPP.SPPClose();
    }

    /**
     * 注册实体
     */
    private android.content.BroadcastReceiver mScanResultReceiver = new android.content.BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(GET_SCANDATA)) {
                Bundle bundle = intent.getExtras();
                final String barcode = bundle.getString(SCAN_DATA);
                Message msg = mHandle.obtainMessage(UPDATE_LIST, barcode);
                mHandle.sendMessage(msg);
            }
        }
    };

    @SuppressLint("HandlerLeak")
    protected Handler mHandle = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_LIST:
                    methodChannel.invokeMethod(DEVICE_SCAN, msg.obj);
                default:
                    break;
            }
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == BLUE_ENABLE_REQUEST_CODE && resultCode == RESULT_OK) {
            getGetBlueDevicesList();
        } else {
            channelResult.success(null);
        }
    }
}
